package cn.qicaiwang.open.qxyApi.server;

import cn.qicaiwang.open.qxyApi.entity.ApiInvokeLog;
import cn.qicaiwang.open.qxyApi.mapper.ApiInvokeLogMapper;
import cn.qicaiwang.open.qxyApi.util.IpUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.util.Date;
import java.util.Map;
import java.util.UUID;

@Service
@Slf4j
public class ApiInvokeLogService {

    @Autowired
    private ApiInvokeLogMapper apiInvokeLogMapper;


    public ApiInvokeLog logApiInvoke(String apiName, String apiPath, String requestMethod,
                                     Map<String, String> headers, Map<String, Object> params,
                                     String requestBody, String responseBody, boolean success,
                                     String errorCode, String errorMessage, Throwable exception,String serverIp) {

        HttpServletRequest request = ((ServletRequestAttributes)
                RequestContextHolder.getRequestAttributes()).getRequest();

        ApiInvokeLog log = new ApiInvokeLog();
        log.setTraceId(generateTraceId());
        log.setApiName(apiName);
        log.setApiPath(apiPath);
        log.setAppKey(getCurrentAppKey());
        log.setInvokeTime(new Date());
        log.setRequestMethod(requestMethod);
        log.setRequestHeaders(JSON.toJSONString(headers));
        log.setRequestParams(JSON.toJSONString(params));
        log.setRequestBody(truncateIfTooLong(requestBody, 4000));
        log.setResponseBody(truncateIfTooLong(responseBody, 4000));
        log.setSuccess(success);
        log.setErrorCode(errorCode);
        log.setErrorMessage(truncateIfTooLong(errorMessage, 1000));
        log.setExceptionStack(getExceptionStack(exception));
        log.setClientIp(IpUtils.getClientIp(request));
        log.setServerIp(serverIp);
        log.setUserAgent(request.getHeader("User-Agent"));

        // 计算耗时
        if (log.getInvokeTime() != null) {
            log.setCostTime(System.currentTimeMillis() - log.getInvokeTime().getTime());
        }

        // 解析响应码
        try {
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            if (jsonResponse != null) {
                log.setResponseCode(jsonResponse.getString("code"));
            }
        } catch (Exception e) {

        }

        // 保存日志
        apiInvokeLogMapper.insert(log);

        return log;
    }

    private String generateTraceId() {
        return UUID.randomUUID().toString().replace("-", "");
    }

    private String getCurrentAppKey() {
        // 从当前上下文获取AppKey
        return "default_app_key"; // 替换为实际获取逻辑
    }

    private String truncateIfTooLong(String str, int maxLength) {
        if (str == null) {
            return null;
        }
        return str.length() > maxLength ? str.substring(0, maxLength) : str;
    }

    private String getExceptionStack(Throwable exception) {
        if (exception == null) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        sb.append(exception.toString()).append("\n");
        for (StackTraceElement element : exception.getStackTrace()) {
            sb.append("\tat ").append(element).append("\n");
        }
        return truncateIfTooLong(sb.toString(), 4000);
    }
}
